package runninbuddy;

import java.util.Vector;

import net.rim.device.api.gps.BlackBerryLocation;
import net.rim.device.api.system.AccelerometerData;

public class DataCombiner {
	private final Vector accQueue = new Vector();
	private final Vector bbLocationQueue = new Vector();

	public synchronized void put(AccelerometerData accData) {
		if (accData == null)
			throw new IllegalArgumentException(
					"Don't put null AccelerometerData in DataCombiner");
		accQueue.addElement(accData);
		notifyAll();
	}

	public synchronized void put(BlackBerryLocation bbLocation) {
		if (bbLocation == null)
			throw new IllegalArgumentException(
					"Don't put null BlackBerrLocation in DataCombiner");
		bbLocationQueue.addElement(bbLocation);
		notifyAll();
	}

	public synchronized RunnerData take() throws InterruptedException {
		while (accQueue.isEmpty() || bbLocationQueue.isEmpty()) {
			wait();
		}

		return syncedRunnerData();
	}

	private RunnerData syncedRunnerData() {
		BlackBerryLocation firstBBLocation = (BlackBerryLocation) bbLocationQueue
				.firstElement();
		if (!firstBBLocation.isValid()) {
			bbLocationQueue.removeElement(firstBBLocation);
			return new RunnerData(firstBBLocation, null);
		}

		int minDiff = Integer.MAX_VALUE;
		int bestMatchIndex = -1;
		RunnerData retVal = null;

		int accQueueSize = accQueue.size();
		for (int i = 0; i < accQueueSize; ++i) {
			AccelerometerData currentAccData = (AccelerometerData) accQueue
					.elementAt(i);

			if (Math.abs(firstBBLocation.getTimestamp()
					- currentAccData.getLastTimestamp()) < minDiff)
				bestMatchIndex = i;
			else
				break;
		}

		retVal = new RunnerData(firstBBLocation, (AccelerometerData) accQueue
				.elementAt(bestMatchIndex));

		bbLocationQueue.removeElementAt(0);
		for (int i = 0; i <= bestMatchIndex; ++i)
			accQueue.removeElementAt(0);

		return retVal;
	}
}
